在資料庫中,如果在一些有可能會出現race condition的地方,或是需要保證某些query要全部一起執行的狀況,就會需要特別使用transaction以及設定合適的isolation level
在這篇文章中,先暫時不介紹這些isolation level,想介紹的是,這個isolation level以及transaction是樂觀鎖還是悲觀鎖呢?
先看看如果transaction如果失敗了會發生什麼事情
有兩個交易,Transaction A 和 Transaction B,都要更新同一個帳戶的餘額。
就算是最高等級的Serializable的Isolation Level,流程如下
1.Transaction A 讀取帳戶餘額為 $100。
2.Transaction B 也讀取帳戶餘額為 $100。
3.Transaction A 增加 $50,嘗試更新餘額為 $150。
4.Transaction B 減少 $30,嘗試更新餘額為 $70。
在 Serializable 隔離級別下,系統會檢測到這種衝突。可能的處理方式是:
這種會讓後來的人發現資料版本有問題,然後讓後來的Transaction重試的過程,就是某種程度的樂觀鎖
我先相信衝突不會一直發生,等到我要提交的時候,檢查當前資料版本跟之前的是否相同
如果相同就提交,失敗就rollback
所以如果實際上需要在資料庫內實現悲觀鎖,不僅僅是下update/delete這種操作,而且還要去針對你需要的資料取得讀鎖或是讀寫鎖,透過資料庫的鎖來讓你的transaction知道有其他人正在用這筆資料,所以應該要等待原先的tx執行完才能繼續